#include <vector>
#include <string>
#include <algorithm>
using namespace std;
/*
给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ，然后串联起所有整数，可以构造一个 表达式 ：

例如，nums = [2, 1] ，可以在 2 之前添加 '+' ，在 1 之前添加 '-' ，然后串联起来得到表达式 "+2-1" 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

 

示例 1：

输入：nums = [1,1,1,1,1], target = 3
输出：5
解释：一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
示例 2：

输入：nums = [1], target = 1
输出：1

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
*/
class Solution
{
public:
    int findTargetSumWays(vector<int> &nums, int target)
    {
        int sum = 0;
        for (int i = 0; i < nums.size(); i++)
        {
            sum += nums[i];
        }
        if (sum < target || (sum + target) % 2 == 1)
        {
            return 0;
        }
        int w = (sum + target) / 2;
        vector<int> dp(w + 1);
        dp[0] = 1;
        for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++)
        {
            for (int j = w; j >= *it; j--)
            {
                dp[j] += dp[j - (*it)];
            }
        }
        return dp[w];
    }

    //Another
    int findTargetSumWays2(vector<int> &nums, int target)
    {
        int sum = 0;
        for (int &num : nums)
        {
            sum += num;
        }
        int diff = sum - target;
        if (diff < 0 || diff % 2 != 0)
        {
            return 0;
        }
        int n = nums.size(), neg = diff / 2;
        vector<vector<int>> dp(n + 1, vector<int>(neg + 1));
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++)
        {
            int num = nums[i - 1];
            for (int j = 0; j <= neg; j++)
            {
                dp[i][j] = dp[i - 1][j];
                if (j >= num)
                {
                    dp[i][j] += dp[i - 1][j - num];
                }
            }
        }
        return dp[n][neg];
    }
};